home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / procssng / fbm.lzh / FBM / fbm10.zoo / flflyd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-25  |  4.5 KB  |  167 lines

  1. /*****************************************************************
  2.  * flflyd.c: FBM Release 1.0 25-Feb-90 Michael Mauldin
  3.  *
  4.  * Copyright (C) 1989,1990 by Michael Mauldin.  Permission is granted
  5.  * to use this file in whole or in part for any purpose, educational,
  6.  * recreational or commercial, provided that this copyright notice
  7.  * is retained unchanged.  This software is available to all free of
  8.  * charge by anonymous FTP and in the UUNET archives.
  9.  *
  10.  * flflyd.c: 
  11.  *
  12.  * CONTENTS
  13.  *    floyd_fbm (input, output)
  14.  *
  15.  * EDITLOG
  16.  *    LastEditDate = Mon Jun 25 00:07:41 1990 - Michael Mauldin
  17.  *    LastFileName = /usr2/mlm/src/misc/fbm/flflyd.c
  18.  *
  19.  * HISTORY
  20.  * 25-Jun-90  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
  21.  *    Package for Release 1.0
  22.  *
  23.  * 20-May-89  Michael Mauldin (mlm) at Carnegie Mellon University
  24.  *    Bug fix from Dave Cohrs <dave@cs.wisc.edu>
  25.  *
  26.  * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  27.  *    Beta release (version 0.9) mlm@cs.cmu.edu
  28.  *
  29.  * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  30.  *    Created.
  31.  *****************************************************************/
  32.  
  33. # include <stdio.h>
  34. # include <math.h>
  35. # include <ctype.h>
  36. # include "fbm.h"
  37.  
  38. /*****************************************************************
  39.  * floyd_fbm: Classical Floyd-Steinberg Halftoning
  40.  *
  41.  * REFERENCES
  42.  *    Digital Halftoning, by Robert Ulichney (1986 MIT Press)
  43.  *****************************************************************/
  44.  
  45. # define RAND(RN) (((seed = 1103515245 * seed + 12345) >> 12) % (RN))
  46. # define INITERR(X,Y) \
  47.     (((int) X) - (((int) Y)?WHITE:BLACK) + ((WHITE/2)-((int) X))/2)
  48.  
  49. #ifndef lint
  50. static char *fbmid =
  51. "$FBM flflyd.c <1.0> 25-Jun-90  (C) 1989,1990 by Michael Mauldin, source \
  52. code available free from MLM@CS.CMU.EDU and from UUNET archives$";
  53. #endif
  54.  
  55. floyd_fbm (input, output)
  56. FBM *input, *output;
  57. { register unsigned char *bmp, *obm;
  58.   register int i, j, rowlen, gray, error, w, h, den, outrow;
  59.   int *lerr, *cerr, *terr;
  60.   register int seed = 0;
  61.  
  62.   if (input->hdr.planes != 1)
  63.   { fprintf (stderr, "floyd_fbm: can't halftone color images\n");
  64.     return (0);
  65.   }
  66.  
  67.   fprintf (stderr, "Floyd-Steinberg halftoning\n");
  68.  
  69.   /* Allocate output */
  70.   free_fbm (output);
  71.   output->hdr = input->hdr;
  72.   output->hdr.bits = 1;
  73.   output->hdr.physbits = 8;
  74.   outrow = 16 * ((input->hdr.cols + 15) / 16); /* Pad to even byte boundary */
  75.   output->hdr.rowlen = outrow;
  76.   output->hdr.plnlen = outrow*output->hdr.rows;
  77.   alloc_fbm (output);
  78.  
  79.   w = input->hdr.cols;
  80.   h = input->hdr.rows;
  81.   rowlen = input->hdr.rowlen;
  82.   
  83.   /* Allocate space for error arrays */
  84.   lerr = (int *) malloc (w * sizeof (*lerr));
  85.   cerr = (int *) malloc (w * sizeof (*cerr));
  86.   for (i=0; i<w; i++) lerr[i] = cerr[i] = 0;
  87.  
  88.   /* The left border */
  89.   error = 0;
  90.   for (j=0; j<h; j++)
  91.   { register int thresh = (WHITE/2 + RAND (129) - 64);
  92.  
  93.     gray = input->bm[j*rowlen] + error;
  94.     den = gray > thresh ? WHITE : BLACK;
  95.     error = gray - den;
  96.     output->bm[j*outrow] = den;
  97.   }
  98.  
  99.   /* The right border */
  100.   error = 0;
  101.   for (j=0; j<h; j++)
  102.   { register int thresh = (WHITE/2 + RAND (129) - 64);
  103.  
  104.     gray = input->bm[j*rowlen + (w-1)] + error;
  105.     den = gray > thresh ? WHITE : BLACK;
  106.     error = gray - den;
  107.     output->bm[j*outrow + (w-1)] = den;
  108.   }
  109.  
  110.   /* The top border */
  111.   error = 0;
  112.   for (i=0; i<w; i++)
  113.   { register int thresh = (WHITE/2 + RAND (129) - 64);
  114.  
  115.     gray = input->bm[i] + error;
  116.     den = gray > thresh ? WHITE : BLACK;
  117.     error = gray - den;
  118.     output->bm[i] = den;
  119.     lerr[i] = INITERR (input->bm[i], den);
  120.   }
  121.  
  122.   /*
  123.    * Now process the interior bits
  124.    *
  125.    *  Weights:            1 5 3
  126.    *                7 *
  127.    */
  128.  
  129.   for (j=1; j<h; j++)
  130.   { /* scan left to right */
  131.     bmp = &input->bm[j*rowlen];
  132.     obm = &output->bm[j*outrow];
  133.  
  134.     cerr[0] = INITERR (bmp[0], obm[0]);
  135.  
  136.     for (i=1; i<w-1; i++)
  137.     {
  138.       error =  (lerr[i-1] + 5 * lerr[i] + 3 * lerr[i+1] + 7 * cerr[i-1]) / 16;
  139.  
  140. # ifdef DEBUG
  141.       if (i > 5 && i < 9 && j > 5 && j < 9)
  142.       { fprintf (stderr, "<%2d,%2d>  Input %3d, Error %5d, Output %d\n",
  143.          i, j, bmp[i], error, bmp[i] + error > (WHITE/2));
  144.     fprintf (stderr, "Errors:   %5d  %5d  %5d\n          %5d      *\n\n", 
  145.          lerr[i-1], lerr[i], lerr[i+1], cerr[i-1]);
  146.       }
  147. # endif
  148.  
  149.       gray = bmp[i] + error;
  150.  
  151.       if (gray > (WHITE/2))
  152.       { obm[i] = WHITE;    cerr[i] = gray - WHITE; }
  153.       else
  154.       { obm[i] = BLACK;    cerr[i] = gray - BLACK; }
  155.     }
  156.     
  157.     /* Set errors for ends of the row */
  158.     cerr[0]   = INITERR (bmp[0], obm[0]);
  159.     cerr[w-1] = INITERR (bmp[w-1], obm[w-1]);
  160.     
  161.     /* Swap error buffers */
  162.     terr = lerr; lerr = cerr; cerr = terr;
  163.   }
  164.   
  165.   return (1);
  166. }
  167.